home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
301-325
/
disk_319
/
cnewssrc
/
cnews.src.lzh
/
libcnews
/
string.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-07-13
|
6KB
|
253 lines
/*
* string operations
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include "libc.h"
#include "news.h"
/* forwards */
char *findhost();
/*
* Return strsave() of the first word in "tokens".
* Words are delimited by spaces.
*/
char *first(tokens)
char *tokens;
{
return strsvto(tokens, ' ');
}
/*
* Turn a newsgroup name into a file name, in place.
*/
void mkfilenm(ng)
register char *ng;
{
for (; *ng != '\0'; ng++)
if (*ng == NGDELIM)
*ng = FNDELIM;
}
void trim(s) /* trim trailing newline */
char *s;
{
register char *nl;
INDEX(s, '\n', nl);
if (nl != NULL)
*nl = '\0';
}
char *skipsp(s) /* skip any whitespace at *s */
register char *s;
{
while (iswhite(*s))
s++;
return s;
}
char *strsvto(s, c) /* save s up to (but excluding) c */
char *s;
int c;
{
register char *endp, *copy;
endp = index(s, c); /* find interesting part's end of s */
if (endp != NULL)
*endp = '\0'; /* restored below */
copy = strsave(s); /* copy interesting substring of s */
if (endp != NULL)
*endp = c;
return copy;
}
int charcount(s, c) /* how many c's in s? */
register char *s;
register int c;
{
register int count = 0;
#ifdef CLASSY
for (; (s = index(s, c)) != NULL; s = (s == NULL? NULL: s+1))
++count;
#else
while (*s != '\0')
if (*s++ == c)
++count;
#endif /* CLASSY */
return count;
}
char *nullify(s) /* return s or "" if NULL */
register char *s;
{
if (s == NULL)
return "";
else
return s;
}
/*
* If c is NUL, hostchar will be false, so don't test (optimisation: ==).
*/
#define nothostchar(c, ch) (!hostchar(c, ch) /* || (c) == '\0' */ )
/*
* True if c can be part of a hostname. RFC 850 allows letters, digits,
* periods, and hyphens and specifically disallows blanks. False may
* mean c is NUL.
*/
#define hostchar(c, ch) ((ch) = (c), \
(isascii(ch) && isalnum(ch) || (ch) == '.' || (ch) == '-'))
/*
* Return true iff any host in hosts appears in s, as per hostin().
* hosts are separated by non-hostname characters.
*/
boolean anyhostin(hosts, s)
char *hosts, *s;
{
register char *host = hosts;
while (*host != '\0') {
register char *delimp;
register int ch;
register int delim;
register boolean hostisin;
while (nothostchar(*host, ch) && *host != '\0')
++host; /* skip leading delims */
if (*host == '\0') /* no more hosts */
break;
for (delimp = host; hostchar(*delimp, ch); delimp++)
; /* skip to next delim */
delim = *delimp; /* may be NUL */
*delimp = '\0'; /* terminate host */
hostisin = hostin(host, s);
*delimp = delim; /* restore hosts delimiter */
if (hostisin)
return YES;
host = delimp; /* advance to next host */
}
return NO;
}
/*
* Return true iff host appears in s, with no characters from the alphabet
* of legal hostname characters immediately adjacent.
*/
boolean hostin(host, s)
register char *host, *s;
{
return findhost(host, s) != NULL;
}
/*
* Return the number of machines appearing in path,
* by counting transitions from delimiters.
* See hostin() for the rules, and the macros.
*/
int hopcount(path)
register char *path;
{
register int count = 0;
register int ch;
for (; *path != '\0'; path++)
if (nothostchar(path[0], ch) && hostchar(path[1], ch))
++count; /* trailing edge of delimiters */
return count;
}
char *sendersite(path)
register char *path;
{
register char *p;
register int ch;
static char *sender = NULL;
nnfree(&sender); /* free the last answer */
for (p = path; hostchar(*p, ch); p++)
;
if (*p == '\0') /* only a user name */
return hostname(); /* a local posting */
else {
register int delim = *p;
*p = '\0';
sender = strsave(path); /* copy the first machine name */
*p = delim;
return sender;
}
}
/*
* Canonicalise rawpath: NULL -> "", chop last site (actually user name)
* but not its leading delimiter, and if Approved:, chop everything after
* the site, and its trailing delimiter, from Approved: (or Sender:)
* (user@host). Result is malloced memory.
*/
char *canonpath(rawpath, approved, sender)
char *rawpath, *approved, *sender;
{
register char *newpath = strsave(nullify(rawpath));
register char *p, *lastdelim = newpath, *site = NULL; /* p-csu v3 */
register int ch;
for (p = newpath; *p != '\0'; ++p)
if (nothostchar(*p, ch))
lastdelim = p + 1; /* just past delim; p-csu v3 */
if (lastdelim != NULL)
*lastdelim = '\0'; /* omit user's name */
if (approved != NULL) { /* moderated article */
site = index(approved, '@');
if (site == NULL)
site = index(nullify(sender), '@');
}
if (site != NULL) {
p = findhost(site+1, newpath);
if (p != NULL && *p++ != '\0') /* delim after site? p-csu v3 */
*p = '\0'; /* terminate newpath after site */
}
return newpath;
}
/*
* Return pointer to the first byte after host in path, if any,
* with no characters from the alphabet of legal hostname characters
* immediately adjacent.
* This function is a profiling hot spot, so it has been optimised.
*/
char *findhost(host, path)
register char *host, *path;
{
register int hostlen = strlen(host), ch;
/* Special case: match host!path or host. */
if (STREQN(path, host, hostlen) && nothostchar(path[hostlen], ch))
return &path[hostlen];
/* Match path2!host!path or path2!host. */
while (*path != '\0')
if (hostchar(path[0], ch)) /* can't start after here */
++path;
else if ((++path, STREQN(path, host, hostlen)) &&
nothostchar(path[hostlen], ch))
return &path[hostlen];
return NULL;
}